package sql.executor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import logging.transaction.TransactionLogger;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.UseStatement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.alter.AlterExpression;
import net.sf.jsqlparser.statement.create.schema.CreateSchema;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.table.ForeignKeyIndex;
import net.sf.jsqlparser.statement.create.table.Index;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import session.Session;
import sql.constraints.ConstraintType;
import sql.constraints.TableConstraint;
import storage.StorageException;
import storage.data.DataManager;
import storage.manager.DatabaseManager;
import storage.manager.TableManager;

public class SQLExecutor {

    // 内部类，用于封装从 CREATE TABLE 语句中解析出的待处理约束信息
    public static class PendingConstraintDetail {
        String name; // 可选，可能由用户指定或稍后生成
        ConstraintType type;
        List<String> columns;
        String checkExpression; // For CHECK constraints
        String referencedTable; // For FOREIGN KEY
        List<String> referencedColumns; // For FOREIGN KEY

        public PendingConstraintDetail(String name, ConstraintType type, List<String> columns) {
            this.name = name;
            this.type = type;
            this.columns = new ArrayList<>(columns); // Ensure mutable list
        }

        // Setter for CHECK specific fields
        public void setCheckDetails(String expression) {
            this.checkExpression = expression;
        }

        // Setter for FOREIGN KEY specific fields
        public void setForeignKeyDetails(String refTable, List<String> refCols) {
            this.referencedTable = refTable;
            this.referencedColumns = refCols != null ? new ArrayList<>(refCols) : new ArrayList<>();
        }
    }

    // 内部类，用于封装 parseSchema 的多个返回结果
    public static class ParsedCreateTableParts {
        public final List<String[]> basicColumnDefinitions; // name, type, length
        public final List<PendingConstraintDetail> pendingConstraints;

        public ParsedCreateTableParts(List<String[]> basicColumnDefinitions, List<PendingConstraintDetail> pendingConstraints) {
            this.basicColumnDefinitions = basicColumnDefinitions;
            this.pendingConstraints = pendingConstraints;
        }
    }

    /**
     * 创建数据库（新存储方案）
     * 流程说明：
     * 1. 初始化存储目录（幂等操作）
     * 2. 在系统表注册数据库信息
     * 3. 建立用户与数据库的映射关系
     */
    public static int executeCreateDatabase(CreateSchema createSchema, String username) {
        try {
            // 清理和验证数据库名称
            String dbName = createSchema.getSchemaName().trim();
            if (dbName.endsWith(";")) {
                dbName = dbName.substring(0, dbName.length() - 1).trim();
            }
            if (dbName.isEmpty()) {
                System.err.println("❌ 创建数据库失败：数据库名称不能为空。");
                return 0;
            }
            if (!dbName.matches("[a-zA-Z_][a-zA-Z0-9_]*")) {
                System.err.println("❌ 创建数据库失败：数据库名称只能包含字母、数字和下划线，且不能以数字开头。");
                return 0;
            }
            if (dbName.equalsIgnoreCase("system_db")) {
                throw new StorageException("禁止创建系统数据库");
            }

            int result = DatabaseManager.createDatabase(dbName, username);
            return result;
        } catch (StorageException e) {
            System.err.println("❗ 数据库创建失败: " + e.getMessage());
            return 0;
        }

    }

    public static int executeCreateDatabase(CreateSchema createSchema) {
        return executeCreateDatabase(createSchema, null);
    }

    /**
     * 创建表（事务性版本）
     * 参数要求 schemaList 需符合 TableManager 的格式规范
     */
    public static int executeCreateTable(CreateTable createTable) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = null;
        String tableName = null;

        if (!txLogger.isTransactionActive()) {
            System.err.println("错误: CREATE TABLE 操作需要在活动的事务中执行。请先使用 'USE database_name;'");
            return 0;
        }
        try {
            dbName = txLogger.getTransactionDatabaseName();
            if (dbName == null) {
                System.err.println("严重错误: 事务已激活但没有关联的数据库名称(CREATE TABLE)。");
                // No rollback here by txLogger as the transaction context itself is broken.
                // Session clearing might still be relevant if a DB was previously set and USE failed partially.
                Session specificSession = Session.getCurrentSession();
                if(specificSession != null) specificSession.clearCurrentDatabaseAfterRollback(); // This method in Session should handle clearing its own state
                return 0;
            }
            Session currentSession = Session.getCurrentSession();
            String sessionDbName = null;
            String sessionDbOwner = null;
            if (currentSession != null) {
                sessionDbName = currentSession.getCurrentDatabaseName();
                sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
            }

            String txDbOwner = txLogger.getTransactionOwnerName(); // Get owner from transaction

            if (sessionDbName == null || !sessionDbName.equals(dbName) || sessionDbOwner == null || !sessionDbOwner.equals(txDbOwner)) {
                 System.err.println("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + txDbOwner + "." + dbName + "') 不符(CREATE TABLE)。");
                 return 0;
            }
            tableName = createTable.getTable().getName();
            System.out.println("[DEBUG] (事务内) 准备解析 CREATE TABLE 语句: " + tableName + " 在数据库: " + dbName);
            ParsedCreateTableParts parsedParts = parseSchema(createTable);

            System.out.println("[DEBUG] (事务内) 准备调用 TableManager.createTable (简化版) for " + tableName);
            int tableCreationResult = TableManager.createTable(dbName, tableName, parsedParts.basicColumnDefinitions);

            if (tableCreationResult == 0) {
                System.err.println("错误: TableManager.createTable 基础结构创建失败。表可能已存在或发生其他错误。");
                throw new StorageException("TableManager.createTable 基础结构创建失败，表可能已存在或发生其他错误。");
            }
            System.out.println("✅ (事务内) 表 ["+tableName+"] 基础结构创建成功。准备添加约束...");

            if (parsedParts.pendingConstraints != null && !parsedParts.pendingConstraints.isEmpty()) {
                System.out.println("[DEBUG] (事务内) 发现 " + parsedParts.pendingConstraints.size() + " 个待处理约束 for " + tableName);
                for (PendingConstraintDetail pcd : parsedParts.pendingConstraints) {
                    TableConstraint constraintToAdd = null;
                    try {
                        String cName = pcd.name;
                        // Generate a default name if parsing didn't assign one AND it's not a type that usually has user-defined names or implies global uniqueness (like PK)
                        if (cName == null && !(pcd.type == ConstraintType.PRIMARY_KEY && pcd.columns.size() == 1)) { // Avoid auto-name for simple col PK for now, pk_table_col is better
                             cName = pcd.type.name().toLowerCase() + "_" + tableName + "_" +
                                    (pcd.columns.isEmpty() ? "table" : String.join("_",pcd.columns).replaceAll("[^a-zA-Z0-9_]", "")) +
                                    "_" + (System.currentTimeMillis() % 10000);
                             System.out.println("[DEBUG] 为类型 "+pcd.type+" 的约束自动生成名称: " + cName);
                        }
                        // If it's a PK and still no name (e.g. table level PK with no CONSTRAINT keyword)
                        if (pcd.type == ConstraintType.PRIMARY_KEY && cName == null) {
                            cName = "pk_" + tableName; // Default PK name for table
                        }


                        if (pcd.type == ConstraintType.FOREIGN_KEY) {
                            if (cName == null) cName = "fk_" + tableName + "_" + String.join("_", pcd.columns).replaceAll("[^a-zA-Z0-9_]", "");
                            constraintToAdd = TableConstraint.createForeignKeyConstraint(
                                cName, pcd.columns, pcd.referencedTable, pcd.referencedColumns);
                        } else if (pcd.type == ConstraintType.CHECK) {
                            if (cName == null) cName = "chk_" + tableName + "_" + (pcd.columns.isEmpty() ? "expr" : String.join("_", pcd.columns).replaceAll("[^a-zA-Z0-9_]", "")) + "_" + (System.currentTimeMillis()%1000);
                            constraintToAdd = TableConstraint.createCheckConstraint(
                                cName, pcd.checkExpression, pcd.columns
                            );
                        } else {
                             if (cName == null && pcd.type == ConstraintType.PRIMARY_KEY && pcd.columns.size() == 1){
                                // For column-level PK like `id INT PRIMARY KEY` where `pk_tableName_colName` was generated by parseSchema
                                // we prefer that over a generic `pk_tableName` if it's a single column PK defined at column level.
                                // parseSchema already creates names like pk_table_col for this specific case.
                                // This block is to ensure if a name was *explicitly* set to null by parsing for some reason, we fix it.
                                // However, current parseSchema for col-level PK generates a name. So this cName==null check might be redundant here.
                                cName = "pk_" + tableName + "_" + pcd.columns.get(0);
                            } else if (cName == null && pcd.type == ConstraintType.NOT_NULL && pcd.columns.size() == 1 && pcd.name != null && pcd.name.startsWith("nn_")){
                                cName = pcd.name; // Retain specific nn_ names generated by parseSchema (e.g. for PK implicits)
                            } else if (cName == null && pcd.type == ConstraintType.UNIQUE && pcd.columns.size() >= 1) {
                                cName = "uk_" + tableName + "_" + String.join("_", pcd.columns).replaceAll("[^a-zA-Z0-9_]", "");
                            }
                            // Fallback if name is still null for some reason for PK/UNIQUE/NN
                            if (cName == null) {
                                 cName = pcd.type.name().toLowerCase() + "_" + tableName + "_" +
                                    (pcd.columns.isEmpty() ? "rand" : String.join("_",pcd.columns).replaceAll("[^a-zA-Z0-9_]", "")) +
                                    "_" + (System.currentTimeMillis() % 10000);
                                 System.out.println("[WARN] Fallback name generation for " + pcd.type + ": " + cName);
                            }
                            constraintToAdd = new TableConstraint(cName, pcd.type, pcd.columns);
                        }
                         System.out.println("[DEBUG] (事务内) 准备添加约束: " + constraintToAdd.getName() + " TYPE: " + constraintToAdd.getType() + " COLS: " + constraintToAdd.getColumns());

                        int addConstraintResult = TableManager.addConstraint(dbName, tableName, constraintToAdd);
                        if (addConstraintResult == 0) {
                            System.err.println("错误: TableManager.addConstraint 添加约束 '" + constraintToAdd.getName() + "' 失败。");
                            throw new StorageException("添加约束 '" + constraintToAdd.getName() + "' 到表 '" + tableName + "' 失败。");
                        }
                         System.out.println("✅ (事务内) 约束 ["+constraintToAdd.getName()+"] 添加成功到 "+tableName);

                    } catch (IllegalArgumentException | StorageException e) {
                        System.err.println("错误: 构造或添加约束时出错 (" + (pcd.name != null ? pcd.name : "未命名 " + pcd.type) + "): " + e.getMessage());
                        throw e;
                    }
                }
            } else {
                System.out.println("[DEBUG] (事务内) 表 " + tableName + " 没有从CREATE语句解析到待处理的约束。");
            }

            // 如果代码执行到这里，表示表结构和所有约束都已成功添加到事务的 TableManager 层面
            // 移除了对 systemDBEngine.addTableToDatabase 的调用，因为表信息应从目标数据库自身获取
            /*
            try {
                // String txDbOwner = txLogger.getTransactionOwnerName(); // txDbOwner 变量已在此方法前部声明和赋值
                // String currentDbName = txLogger.getTransactionDatabaseName(); // dbName 变量也已在此方法前部获取
                if (txDbOwner != null && dbName != null && tableName != null) {
                    core.engine.systemDBEngine.addTableToDatabase(txDbOwner, dbName, tableName);
                    System.out.println("✅ (元数据) 表 [" + tableName + "] 已添加到数据库 [" + txDbOwner + "." + dbName + "] 的系统元信息中。");
                } else {
                    System.err.println("❌ (元数据) 更新表到系统元信息失败：事务所有者、数据库名或表名为空。 txOwner: " + txDbOwner + ", dbName: " + dbName + ", tableName: " + tableName);
                }
            } catch (Exception metaEx) {
                System.err.println("❌ (元数据) 将表 [" + tableName + "] 添加到数据库 [" + (txLogger.getTransactionOwnerName() != null ? txLogger.getTransactionOwnerName() : "?") + "." + dbName + "] 的系统元信息时出错: " + metaEx.getMessage());
            }
            */

            System.out.println("✅ CREATE TABLE 语句 (包括所有约束) 已在事务中成功排队。");
            return 1;

        } catch (Exception e) {
            System.err.println("❌ CREATE TABLE 执行失败 (事务将回滚): " + (tableName != null ? "表 "+tableName+" " : "") + e.getMessage());
            txLogger.rollbackTransaction();
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return 0;
        }
    }

    /**
     * 删除操作（根据类型分发）
     */
    public static int executeDrop(Drop dropStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String targetDbName = null; // For transaction context comparison
        String targetDbOwner = null; // For transaction context comparison
        String sessionDbName = null;
        String sessionDbOwner = null;

        Session currentSession = Session.getCurrentSession();
        if (currentSession != null) {
             sessionDbName = currentSession.getCurrentDatabaseName();
             sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
        }
        String nameToDrop = null;
        String dropType = null;

        try {
            nameToDrop = dropStmt.getName().getName();
            dropType = dropStmt.getType().toUpperCase();
            if ("DATABASE".equals(dropType)) {
                // This path is hit if JSqlParser parsed a "DROP DATABASE <dbName>" statement.
                // Our system requires "DROP DATABASE <ownerName>.<dbName>", which is handled by SQLParser
                // routing to SQLExecutor.executeDropDatabase(ownerName, dbName).
                // Therefore, reaching here means an unsupported syntax was used.
                System.err.println("❌ 错误: 不支持的 DROP DATABASE 语法. 请使用 'DROP DATABASE ownerName.dbName;'");
                return 0;
            }

            // For other DROP types (TABLE, INDEX etc.)
            if (!txLogger.isTransactionActive()) {
                System.err.println("错误: DROP " + dropType + " 操作需要在活动的事务中执行。请先使用 'USE database_name;'.");
                return 0;
            }

            targetDbName = txLogger.getTransactionDatabaseName();
            targetDbOwner = txLogger.getTransactionOwnerName();

            if (targetDbName == null || targetDbOwner == null) {
                 System.err.println("严重错误: 事务已激活但没有关联的数据库上下文(DROP " + dropType + ")。");
                 if(currentSession != null) currentSession.clearCurrentDatabaseAfterRollback();
                 return 0;
            }
            if (sessionDbName == null || !sessionDbName.equals(targetDbName) || sessionDbOwner == null || !sessionDbOwner.equals(targetDbOwner) ) {
                 System.err.println("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + targetDbOwner + "." + targetDbName + "') 不符(DROP " + dropType + ")。");
                 return 0;
            }

            // Note: TableManager's methods expect only dbName, not ownerName, as they operate on the current transaction's DB instance.
            // The owner context is implicitly handled by which DB instance the transaction is bound to.

            if ("TABLE".equals(dropType)) {
                System.out.println("[DEBUG] (事务内) 准备调用 TableManager.deleteTable: " + nameToDrop + " from DB: " + targetDbName + " (Owner context: " + targetDbOwner + ")");
                // TableManager.deleteTable expects (String dbName, String tableName)
                return TableManager.deleteTable(targetDbName, nameToDrop);
            } else if ("INDEX".equals(dropType)) {
                System.out.println("[DEBUG] (事务内) 准备调用 TableManager.dropIndex (Not fully implemented): " + nameToDrop + " from DB: " + targetDbName);
                System.err.println("错误: DROP INDEX 功能暂未完全实现。");
                return 0;
            } else {
                System.err.println("错误: 不支持的 DROP 类型: " + dropType);
                return 0;
            }
        } catch (Exception e) {
            System.err.println("❌ DROP " + (dropType != null ? dropType : "") + " 执行失败: " + e.getMessage());
            return 0;
        }
    }

    // Note: executeDropDatabase does not need transaction check as it's a meta operation
    // and handles its own systemDB interactions.
    public static int executeDropDatabase(String ownerName, String dbName) {
        System.out.println("[INFO] SQLExecutor: Executing DROP DATABASE " + ownerName + "." + dbName);
        try {
            // Before deleting, check if this is the current database for any active session or transaction.
            // This is a complex check across all sessions. For simplicity, we'll rely on users
            // not dropping a database they are actively using in another transaction/session.
            // Or, DatabaseManager.deleteDatabase could have checks to prevent deletion of "active" DBs.

            // If the database to be dropped is the one currently set in the *calling* session's context, clear it.
            Session currentSession = Session.getCurrentSession();
            if (currentSession != null) {
                String currentSessionDbName = currentSession.getCurrentDatabaseName();
                String currentSessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
                if (dbName.equals(currentSessionDbName) && ownerName.equals(currentSessionDbOwner)) {
                    System.out.println("[INFO] Dropping the current session's database. Clearing session context.");
                    // currentSession.setCurrentDatabase(null); // OLD
                    currentSession.setCurrentDatabase(null, null); // NEW
                }
            }

            // Also, if this database is the one in the current TransactionLogger's context,
            // the transaction *must* be ended (committed or rolled back) before dropping.
            // For now, we assume higher layers (like SQLParser or Session) ensure this,
            // or DatabaseManager.deleteDatabase has guards.
            // A simple check:
            TransactionLogger txLogger = TransactionLogger.getInstance();
            if (txLogger.isTransactionActive() &&
                dbName.equals(txLogger.getTransactionDatabaseName()) &&
                ownerName.equals(txLogger.getTransactionOwnerName())) {
                System.err.println("❌ 错误: 无法删除数据库 '" + ownerName + "." + dbName + "'，因为它正在一个活动事务中使用。请先 COMMIT 或 ROLLBACK。");
                return 0;
            }

            int result = DatabaseManager.deleteDatabase(ownerName, dbName);
            if (result == 1) {
                System.out.println("✅ 数据库 " + ownerName + "." + dbName + " 已成功删除。");
            } else {
                System.err.println("❌ 数据库 " + ownerName + "." + dbName + " 删除失败 (DatabaseManager报告)。");
            }
            return result;
        } catch (Exception e) {
            System.err.println("❌ 执行 DROP DATABASE " + ownerName + "." + dbName + " 时发生意外错误: " + e.getMessage());
            return 0;
        }
    }

    public static int executeAlter(Alter alterStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = null;
        String ownerName = null; // Added for owner context
        String tableName = null;
        Session currentSession = Session.getCurrentSession();
        String sessionDbName = null;
        String sessionDbOwner = null;

        if (!txLogger.isTransactionActive()) {
            System.err.println("错误: ALTER TABLE 操作需要在活动的事务中执行。请先使用 'USE database_name;'.");
            return 0;
        }
        try {
            dbName = txLogger.getTransactionDatabaseName();
            ownerName = txLogger.getTransactionOwnerName(); // Get owner from transaction
            if (dbName == null || ownerName == null) {
                 System.err.println("严重错误: 事务已激活但没有完整的数据库上下文(ALTER TABLE)。");
                 if(currentSession != null) currentSession.clearCurrentDatabaseAfterRollback();
                 return 0;
            }

            if (currentSession != null) {
                sessionDbName = currentSession.getCurrentDatabaseName();
                sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
            }
            if (sessionDbName == null || !sessionDbName.equals(dbName) || sessionDbOwner == null || !sessionDbOwner.equals(ownerName) ) {
                 System.err.println("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + ownerName + "." + dbName + "') 不符(ALTER TABLE)。");
                 return 0;
            }

            Table table = alterStmt.getTable();
            tableName = table.getName();

            // 打印整个 ALTER 语句的 toString()
            System.out.println("[DEBUG] executeAlter: Received ALTER statement: " + alterStmt.toString());

            // 4. 遍历并执行AlterExpression (调用 TableManager 的方法)
            List<AlterExpression> alterExpressions = alterStmt.getAlterExpressions();
            if (alterExpressions == null || alterExpressions.isEmpty()) {
                 System.out.println("提示: ALTER 语句没有指定具体操作。");
                 return 1; // 无操作视为成功
            }

            for (AlterExpression expr : alterExpressions) {
                // 打印当前 AlterExpression 的 toString() 和 getOperation().toString()
                System.out.println("[DEBUG] executeAlter: Processing AlterExpression: " + expr.toString());
                System.out.println("[DEBUG] executeAlter: expr.getOperation(): " + expr.getOperation().toString());

                String operationTypeStr = expr.getOperation().toString().toUpperCase();
                int operationResult = 0;
                TableConstraint newConstraint = null;

                if ("ADD".equals(operationTypeStr)) {
                    if (expr.getColDataTypeList() != null && !expr.getColDataTypeList().isEmpty()) {
                        // ADD COLUMN
                        net.sf.jsqlparser.statement.alter.AlterExpression.ColumnDataType alterColDataType = expr.getColDataTypeList().get(0);
                        String columnName = alterColDataType.getColumnName();

                        net.sf.jsqlparser.statement.create.table.ColDataType createTableColDataType = alterColDataType.getColDataType();

                        // <<< 新增的调试打印 >>>
                        System.out.println("[DEBUG SQLExecutor] alterColDataType.toString(): " + alterColDataType.toString());
                        System.out.println("[DEBUG SQLExecutor] createTableColDataType.toString(): " + createTableColDataType.toString());
                        System.out.println("[DEBUG SQLExecutor] createTableColDataType.getDataType(): " + createTableColDataType.getDataType());
                        if (createTableColDataType.getArgumentsStringList() != null && !createTableColDataType.getArgumentsStringList().isEmpty()) {
                            System.out.println("[DEBUG SQLExecutor] createTableColDataType.getArgumentsStringList(): " + String.join(", ", createTableColDataType.getArgumentsStringList()));
                        } else {
                            System.out.println("[DEBUG SQLExecutor] createTableColDataType.getArgumentsStringList(): null or empty");
                        }
                        System.out.println("[DEBUG SQLExecutor] expr.toString(): " + expr.toString()); // expr is in scope here
                        if (expr.getPkColumns() != null && !expr.getPkColumns().isEmpty()) {
                            System.out.println("[DEBUG SQLExecutor] expr.getPkColumns(): " + expr.getPkColumns());
                        } else {
                            System.out.println("[DEBUG SQLExecutor] expr.getPkColumns(): null or empty");
                        }
                        if (expr.getIndex() != null) {
                            System.out.println("[DEBUG SQLExecutor] expr.getIndex().toString(): " + expr.getIndex().toString());
                            System.out.println("[DEBUG SQLExecutor] expr.getIndex().getType(): " + expr.getIndex().getType());
                            if (expr.getIndex().getColumns() != null && !expr.getIndex().getColumns().isEmpty()) {
                                System.out.println("[DEBUG SQLExecutor] expr.getIndex().getColumns(): " + expr.getIndex().getColumns());
                            } else {
                                System.out.println("[DEBUG SQLExecutor] expr.getIndex().getColumns(): null or empty");
                            }
                        } else {
                            System.out.println("[DEBUG SQLExecutor] expr.getIndex(): null");
                        }
                        // <<< 调试打印结束 >>>

                        String dataTypeStringOnly = createTableColDataType.getDataType();
                        String fullDataTypeString = dataTypeStringOnly; // Re-initialize fullDataTypeString
                        if (createTableColDataType.getArgumentsStringList() != null && !createTableColDataType.getArgumentsStringList().isEmpty()) {
                            fullDataTypeString += "(" + String.join(",", createTableColDataType.getArgumentsStringList()) + ")";
                        }

                        if (columnName == null || fullDataTypeString == null) {
                            System.err.println("❌ ALTER ADD COLUMN 缺少列信息。");
                            throw new StorageException("ALTER ADD COLUMN 缺少列信息");
                        }
                        System.out.println("[DEBUG] (事务内) 准备执行 ALTER TABLE " + tableName + " ADD COLUMN " + columnName + " " + fullDataTypeString);

                        // 为不同的数据类型设置合适的默认长度
                        String adjustedDataType = fullDataTypeString;
                        if (dataTypeStringOnly.equalsIgnoreCase("INT") || dataTypeStringOnly.equalsIgnoreCase("INTEGER")) {
                            // 如果是 INT 类型且没有指定长度，则使用 11 作为默认长度
                            if (!adjustedDataType.contains("(")) {
                                adjustedDataType = dataTypeStringOnly + "(11)";
                                System.out.println("[DEBUG] 调整 INT 类型的默认长度为 11: " + adjustedDataType);
                            }
                        } else if ((dataTypeStringOnly.equalsIgnoreCase("VARCHAR") || dataTypeStringOnly.equalsIgnoreCase("CHAR")) && !adjustedDataType.contains("(")) {
                            // VARCHAR 和 CHAR 需要长度参数
                            adjustedDataType = dataTypeStringOnly + "(255)";
                            System.out.println("[DEBUG] 调整 VARCHAR/CHAR 类型的默认长度为 255: " + adjustedDataType);
                        }

                        operationResult = TableManager.addColumn(dbName, tableName, columnName, adjustedDataType);

                        if (operationResult == 1) {
                            boolean columnIsPrimaryKey = false;
                            List<String> pkDefiningColumnList = null; // Will hold the column name if it's a PK

                            // 1. 尝试通过 AlterExpression 顶层属性获取主键信息
                            if (expr.getPkColumns() != null && !expr.getPkColumns().isEmpty()) {
                                if (expr.getPkColumns().contains(columnName)) {
                                    columnIsPrimaryKey = true;
                                    pkDefiningColumnList = java.util.Collections.singletonList(columnName);
                                    System.out.println("[DEBUG] 主键通过 expr.getPkColumns() 识别 for column " + columnName);
                                }
                            } else if (expr.getIndex() != null && "PRIMARY KEY".equalsIgnoreCase(expr.getIndex().getType())) {
                                if (expr.getIndex().getColumns().stream().anyMatch(idxCol -> idxCol.getColumnName().equalsIgnoreCase(columnName))) {
                                    columnIsPrimaryKey = true;
                                    pkDefiningColumnList = java.util.Collections.singletonList(columnName);
                                    System.out.println("[DEBUG] 主键通过 expr.getIndex() 识别 for column " + columnName);
                                }
                            }

                            // 2. 如果顶层属性未识别出主键，尝试检查 ALTER TABLE 语句本身是否包含 PRIMARY KEY 关键字
                            String alterStatementStr = expr.toString().toUpperCase();
                            System.out.println("[DEBUG] ALTER 语句字符串: " + alterStatementStr);

                            if (!columnIsPrimaryKey &&
                                (alterStatementStr.contains("PRIMARY KEY") ||
                                 alterStatementStr.contains(columnName.toUpperCase() + " INT PRIMARY") ||
                                 alterStatementStr.contains(columnName.toUpperCase() + " INTEGER PRIMARY"))) {
                                columnIsPrimaryKey = true;
                                pkDefiningColumnList = java.util.Collections.singletonList(columnName);
                                System.out.println("[DEBUG] 主键通过 ALTER 语句字符串识别: " + alterStatementStr);
                            }

                            // 2.5 另外检查整个 ALTER TABLE 语句
                            if (!columnIsPrimaryKey) {
                                String entireStatement = "ALTER TABLE " + tableName + " " + expr.toString();
                                System.out.println("[DEBUG] 完整 ALTER 语句: " + entireStatement);
                                if (entireStatement.toUpperCase().contains("PRIMARY KEY")) {
                                    columnIsPrimaryKey = true;
                                    pkDefiningColumnList = java.util.Collections.singletonList(columnName);
                                    System.out.println("[DEBUG] 主键通过完整 ALTER 语句识别");
                                }
                            }

                            // 3. 如果上述方法都未识别出主键，直接检查 SQL 命令是否包含 PRIMARY KEY
                            if (!columnIsPrimaryKey) {
                                // 之前的方法：直接假设任何语句都是主键
                                // System.out.println("[DEBUG] 强制检查，假设任何包含 PRIMARY KEY 的 ADD COLUMN 语句都是在添加主键列");
                                // columnIsPrimaryKey = true;
                                // pkDefiningColumnList = java.util.Collections.singletonList(columnName);

                                // 新方法：只有当语句中明确包含 PRIMARY KEY 相关内容时才认为是主键
                                String alterSql = alterStmt.toString().toUpperCase();
                                if (alterSql.contains(" PRIMARY KEY") ||
                                    alterSql.contains("PRIMARY KEY(") ||
                                    alterSql.contains("PRIMARY KEY (")) {

                                    // 寻找当前列名是否在 PRIMARY KEY 子句中
                                    if (alterSql.contains(columnName.toUpperCase() + " PRIMARY KEY") ||
                                        alterSql.contains(columnName.toUpperCase() + " INT PRIMARY KEY") ||
                                        alterSql.contains(columnName.toUpperCase() + " INTEGER PRIMARY KEY") ||
                                        alterSql.contains("PRIMARY KEY (" + columnName.toUpperCase()) ||
                                        alterSql.contains("PRIMARY KEY(" + columnName.toUpperCase())) {

                                        columnIsPrimaryKey = true;
                                        pkDefiningColumnList = java.util.Collections.singletonList(columnName);
                                        System.out.println("[DEBUG] 通过精确匹配确认列 " + columnName + " 是主键");
                                    } else {
                                        System.out.println("[DEBUG] SQL 中包含 PRIMARY KEY，但未找到与列 " + columnName + " 的明确关联");
                                    }
                                } else {
                                    System.out.println("[DEBUG] SQL 中未找到 PRIMARY KEY 关键字");
                                }
                            }

                            if (columnIsPrimaryKey && pkDefiningColumnList != null) {
                                String pkConstraintName = "pk_" + tableName + "_" + columnName;
                                TableConstraint pkConstraint = new TableConstraint(pkConstraintName, ConstraintType.PRIMARY_KEY, pkDefiningColumnList);
                                System.out.println("[DEBUG] (事务内) 为新增列 " + columnName + " 准备添加 PRIMARY KEY 约束 " + pkConstraintName);
                                int pkResult = TableManager.addConstraint(dbName, tableName, pkConstraint);
                                if (pkResult == 0) {
                                    throw new StorageException("为新增列 " + columnName + " 添加 PRIMARY KEY 约束 " + pkConstraintName + " 失败。");
                                }

                                // 获取并打印约束状态
                                System.out.println("[DEBUG] (事务内) 明确将主键列 " + columnName + " 的 nullable 属性设置为 false");
                                try {
                                    System.out.println("[DEBUG] 通过TableManager.setColumnNotNull方法直接设置列 " + columnName + " 为非空");
                                    // 使用新实现的setColumnNotNull方法设置列为非空
                                    int notNullResult = TableManager.setColumnNotNull(dbName, tableName, columnName);
                                    if (notNullResult == 1) {
                                        System.out.println("[DEBUG] 已成功将主键列 " + columnName + " 设置为非空");
                                    } else {
                                        System.err.println("[WARNING] 设置主键列 " + columnName + " 为非空失败，但继续处理");
                                    }
                                } catch (Exception e) {
                                    System.err.println("[ERROR] 设置列 " + columnName + " 为非空时出错: " + e.getMessage());
                                }
                            }
                        }
                    }
                    // Try to parse ADD CONSTRAINT, prioritizing CHECK via regex
                    else {
                        String alterExprStr = expr.toString().toUpperCase();
                        String constraintName = expr.getConstraintName(); // JSqlParser might get this for any constraint type
                        List<String> columns = new ArrayList<>();
                        ConstraintType determinedConstraintType = null;

                        // Define regex parts for simple single-column CHECK constraints
                        String columnNameRegex = "\\w+";
                        String operatorRegex = "(?:>|<|>=|<=|=|!=|<>)";
                        String valueRegex = "(?:'[^']*'|\\d+(?:\\\\.\\d+)?)"; // For numeric, allow int or decimal

                        String comparisonExprRegex = columnNameRegex + "\\s*" + operatorRegex + "\\s*" + valueRegex;
                        String betweenExprRegex = columnNameRegex + "\\s+BETWEEN\\s+" + valueRegex + "\\s+AND\\s+" + valueRegex;
                        String validCheckContentRegex = "(?:" + comparisonExprRegex + "|" + betweenExprRegex + ")";

                        Pattern checkPattern = Pattern.compile("CHECK\\s*\\(\\s*(" + validCheckContentRegex + ")\\s*\\)", Pattern.CASE_INSENSITIVE);
                        Matcher checkMatcher = checkPattern.matcher(expr.toString()); // Use original case string for matching content

                        Pattern constraintNamePatternForCheck = Pattern.compile("CONSTRAINT\\s+(\\w+)\\s+CHECK", Pattern.CASE_INSENSITIVE);
                        Matcher nameMatcherForCheck = constraintNamePatternForCheck.matcher(expr.toString());

                        if (alterExprStr.contains("CHECK") && checkMatcher.find()) {
                            determinedConstraintType = ConstraintType.CHECK;
                            String checkCondition = checkMatcher.group(1).trim();
                            List<String> checkInvolvedColumns = new ArrayList<>();
                            // 从 checkCondition 中解析列名 (简单实现，假设列名在操作符前)
                            Pattern columnFromConditionPattern = Pattern.compile("\\b(\\w+)\\b(?:\\s*[><=!]|IGNORE|\\s+BETWEEN\\b)", Pattern.CASE_INSENSITIVE);
                            Matcher columnMatcher = columnFromConditionPattern.matcher(checkCondition);
                            if(columnMatcher.find()){
                                checkInvolvedColumns.add(columnMatcher.group(1));
                                // 如果是 BETWEEN A AND B, A 也是一个列名，可能需要更复杂的解析
                                // 暂时只取第一个匹配到的作为简化处理
                            }
                            if (checkInvolvedColumns.isEmpty()){
                                System.out.println("[WARN] 未能从CHECK条件中解析出列名: " + checkCondition + " 将使用空列列表创建约束。");
                            }

                            if (constraintName == null && nameMatcherForCheck.find()) { // Try to parse name if JSQLParser didn't get it
                                constraintName = nameMatcherForCheck.group(1);
                            }
                            if (constraintName == null) {
                                constraintName = generateDefaultConstraintName("check", tableName, "expr_" + (System.currentTimeMillis()%10000));
                            }
                            newConstraint = TableConstraint.createCheckConstraint(constraintName, checkCondition, checkInvolvedColumns);
                        }
                        // If not a CHECK constraint, or regex failed, try JSqlParser's specific getters for PK, UK, FK
                        else if (expr.getPkColumns() != null && !expr.getPkColumns().isEmpty()) {
                            determinedConstraintType = ConstraintType.PRIMARY_KEY;
                            columns.addAll(expr.getPkColumns());
                            String specificObjectName = null;
                            if (expr.getIndex() != null && expr.getIndex().getName() != null && "PRIMARY KEY".equalsIgnoreCase(expr.getIndex().getType())) {
                                specificObjectName = expr.getIndex().getName();
                            }
                            if (constraintName == null && specificObjectName != null) { constraintName = specificObjectName; }
                            if (constraintName == null) { constraintName = generateDefaultConstraintName("pk", tableName, columns.isEmpty() ? "unnamed" : columns.get(0)); }
                            newConstraint = new TableConstraint(constraintName, determinedConstraintType, columns);
                        } else if (expr.getUkColumns() != null && !expr.getUkColumns().isEmpty()) {
                            determinedConstraintType = ConstraintType.UNIQUE;
                            columns.addAll(expr.getUkColumns());
                            String specificObjectName = null;
                             if (expr.getIndex() != null && expr.getIndex().getName() != null && expr.getIndex().getType().toUpperCase().startsWith("UNIQUE")) {
                                specificObjectName = expr.getIndex().getName();
                            }
                            if (constraintName == null && specificObjectName != null) { constraintName = specificObjectName; }
                            if (constraintName == null) { constraintName = generateDefaultConstraintName("uk", tableName, columns.isEmpty() ? "unnamed" : columns.get(0)); }
                            newConstraint = new TableConstraint(constraintName, determinedConstraintType, columns);
                        } else if (expr.getFkColumns() != null && !expr.getFkColumns().isEmpty()) {
                            determinedConstraintType = ConstraintType.FOREIGN_KEY;
                            columns.addAll(expr.getFkColumns());
                            String refTable = expr.getFkSourceTable();
                            List<String> refCols = expr.getFkSourceColumns();
                            if (refTable == null || refCols == null || refCols.isEmpty()) {
                                throw new StorageException("FOREIGN KEY 约束定义不完整：缺少引用的表或列。");
                            }
                            if (constraintName == null) {
                                constraintName = generateDefaultConstraintName("fk", tableName, columns.isEmpty() ? "multi" : columns.get(0));
                            }
                            newConstraint = TableConstraint.createForeignKeyConstraint(constraintName, columns, refTable, refCols);
                        } else if (constraintName != null) {
                            // Only constraint name is available from JSqlParser, and it wasn't ADD COLUMN, and not parsed as CHECK/PK/UK/FK.
                            System.err.println("⚠️ ALTER TABLE ADD CONSTRAINT " + constraintName + ": JSqlParser提供了约束名，但无法通过特定方法或自定义CHECK解析确定其类型 (PK, UK, FK, CHECK)。该约束可能不被支持或解析不完整。");
                            throw new StorageException("ADD CONSTRAINT 操作 '" + constraintName + "' 类型未知或不受支持。");
                        } else {
                            // This path implies the operation was ADD, but not ADD COLUMN, and no constraint type could be determined.
                            System.err.println("❌ 无法解析的 ADD CONSTRAINT 语句：JSqlParser 未能提供足够信息，自定义CHECK解析也未成功。");
                            throw new StorageException("无法解析的 ADD CONSTRAINT 语句：未能识别约束类型。");
                        }

                        if (newConstraint != null) {
                            System.out.println("[DEBUG] (事务内) 准备执行 ALTER TABLE " + tableName + " ADD CONSTRAINT " + newConstraint.getName() + " TYPE " + newConstraint.getType());
                            operationResult = TableManager.addConstraint(dbName, tableName, newConstraint);
                        } else {
                            // This should ideally not be reached if the logic above is exhaustive for ADD CONSTRAINT,
                            // but acts as a fallback if newConstraint wasn't created despite it being an ADD (non-COLUMN) operation.
                            System.err.println("❌ ALTER ADD 操作未能创建约束对象，即使它似乎是一个约束操作。检查逻辑。 Operation: " + expr.toString());
                            throw new StorageException("未能为ADD操作创建有效的约束对象。");
                        }
                    }
                } else if ("DROP".equals(operationTypeStr)) {
                     String constraintToDrop = expr.getConstraintName();
                     String columnToDrop = expr.getColumnName();

                     if (constraintToDrop != null) {
                        // This is ALTER TABLE ... DROP CONSTRAINT constraint_name
                        System.out.println("[DEBUG] (事务内) 准备执行 ALTER TABLE " + tableName + " DROP CONSTRAINT " + constraintToDrop);
                        operationResult = TableManager.dropConstraint(dbName, tableName, constraintToDrop);
                        // TableManager.dropConstraint will throw an exception on critical failure (e.g. constraint not found)
                        // or return 1 for success, 0 for logical errors like not found (if not throwing exception for it).
                        // Our current TableManager.dropConstraint throws if not found.
                    } else if (columnToDrop != null) {
                        // This is DROP COLUMN (existing logic)
                        if (columnToDrop == null) { // This check is redundant due to else if, but harmless
                             System.err.println("❌ ALTER DROP COLUMN 缺少列名。");
                             throw new StorageException("ALTER DROP COLUMN 缺少列名");
                        }
                        System.out.println("[DEBUG] (事务内) 准备执行 ALTER TABLE " + tableName + " DROP COLUMN " + columnToDrop);
                        operationResult = TableManager.dropColumn(dbName, tableName, columnToDrop);
                    } else {
                        System.err.println("❌ 不支持的 ALTER DROP 操作。请指定要删除的列或约束。");
                        throw new UnsupportedOperationException("不支持的 ALTER DROP 操作。请指定要删除的列或约束。");
                    }
                } else if ("MODIFY".equals(operationTypeStr)) {
                    // 这是 MODIFY COLUMN (已有的逻辑)
                    if (expr.getColDataTypeList() == null || expr.getColDataTypeList().isEmpty()){
                         System.err.println("❌ ALTER MODIFY COLUMN 缺少列信息。");
                         throw new StorageException("ALTER MODIFY COLUMN 缺少列信息");
                    }
                    String columnName = expr.getColDataTypeList().get(0).getColumnName();
                    String dataType = expr.getColDataTypeList().get(0).getColDataType().toString();
                    if (columnName == null || dataType == null) { throw new StorageException("ALTER MODIFY COLUMN 缺少列信息"); }
                    System.out.println("[DEBUG] (事务内) 准备执行 ALTER TABLE " + tableName + " MODIFY COLUMN " + columnName);
                    operationResult = TableManager.modifyColumn(dbName, tableName, columnName, dataType);
                } else {
                    System.err.println("❌ 不支持的 ALTER 操作类型 (顶层): " + operationTypeStr);
                    throw new UnsupportedOperationException("不支持的 ALTER TABLE 操作类型: " + operationTypeStr);
                }

                // 检查单个操作的结果
                if (operationResult == 0) {
                    // 如果 TableManager/DataManager 返回0但未抛异常，说明是逻辑错误（如列不存在）
                    // 这种情况应该导致事务回滚
                    System.err.println("错误: ALTER 操作 ('" + operationTypeStr + "') 在表 '/" + tableName + "' 上失败 (返回0)。");
                    throw new StorageException("ALTER 操作 (" + operationTypeStr + ") 失败。"); // 抛出异常以触发回滚
                }
                // 如果 operationResult 为 1，则继续下一个 alter expression
            }

            // 如果所有 alter expression 都成功排队
            System.out.println("✅ ALTER TABLE 语句已在事务中成功排队。");
            // 移除自动提交，将操作保留在当前事务中，等待显式 COMMIT
            return 1; // 全部操作成功排队

        } catch (Exception e) {
            System.err.println("❌ ALTER TABLE 执行失败 (事务将回滚): " + (tableName != null ? "表 '"+tableName+"'" : "") + " - " + e.getMessage());
            // e.printStackTrace();
            txLogger.rollbackTransaction(); // 回滚事务
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return 0; // 返回失败
        }
    }

    // Helper method to generate default constraint names
    private static String generateDefaultConstraintName(String typePrefix, String tableName, String colHint) {
        return typePrefix + "_" + tableName + "_" + colHint.replaceAll("[^a-zA-Z0-9_]", "") + "_" + System.currentTimeMillis() % 10000;
    }

    /**
     * 执行 INSERT 语句（事务性版本）
     * 新流程：
     * 1. 先从TableManager获取表结构 (需要改为事务化获取)
     * 2. 使用DataManager进行原子化插入 (DataManager已事务化)
     */
    public static int executeInsert(Insert insertStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = null;
        String ownerName = null; // Added
        String tableName = null;
        Session currentSession = Session.getCurrentSession();
        String sessionDbName = null;
        String sessionDbOwner = null;

        if (!txLogger.isTransactionActive()) {
            System.err.println("错误: INSERT 操作需要在活动的事务中执行。请先使用 'USE database_name;'.");
            return 0;
        }
        try {
            dbName = txLogger.getTransactionDatabaseName();
            ownerName = txLogger.getTransactionOwnerName(); // Get owner from transaction
            if (dbName == null || ownerName == null) {
                 System.err.println("严重错误: 事务已激活但没有完整的数据库上下文(INSERT)。");
                 if(currentSession != null) currentSession.clearCurrentDatabaseAfterRollback();
                 return 0;
            }

            if (currentSession != null) {
                sessionDbName = currentSession.getCurrentDatabaseName();
                sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
            }
            if (sessionDbName == null || !sessionDbName.equals(dbName) || sessionDbOwner == null || !sessionDbOwner.equals(ownerName)) {
                 System.err.println("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + ownerName + "." + dbName + "') 不符(INSERT)。");
                 return 0;
            }

            tableName = insertStmt.getTable().getName();

            // 移除旧的DB Name获取逻辑和表存在性检查（让DataManager或TableManager在事务内处理）
            // String dbName = DatabaseManager.getCurrentDatabase();
            // if (!TableManager.tableExists(dbName, tableName)) { ... }

            // 4. 获取表结构信息 (使用事务化的 TableManager.getTableInfo)
            // TableManager.getTableInfo 内部会优先使用事务DB (如果事务激活)
            System.out.println("[DEBUG] (事务内) 准备获取表结构: " + tableName + " 在数据库 " + dbName);
            Map<String, Object> tableInfo = TableManager.getTableInfo(dbName, tableName);
            if (tableInfo == null || tableInfo.isEmpty() || !tableInfo.containsKey("columns")) {
                System.err.println("❌ (事务内) 无法获取表 " + tableName + " 的结构信息。表可能不存在或无权限。");
                throw new StorageException("无法获取表 " + tableName + " 的结构信息。");
            }

            @SuppressWarnings("unchecked")
            List<Map<String, Object>> columnsInfo = (List<Map<String, Object>>) tableInfo.get("columns");
            if (columnsInfo == null || columnsInfo.isEmpty()) {
                 System.err.println("❌ (事务内) 表 " + tableName + " 的结构信息不包含列定义。");
                 throw new StorageException("表 " + tableName + " 缺少列定义。");
            }

            List<String[]> schemaList = new ArrayList<>();
            for (Map<String, Object> colInfo : columnsInfo) {
                String colName = (String) colInfo.get("name");
                String colType = (String) colInfo.get("type");
                Object lengthObj = colInfo.get("length"); // 可能是Integer或String
                String colLengthStr;
                if (lengthObj instanceof Number) {
                    colLengthStr = String.valueOf(((Number)lengthObj).intValue());
                } else if (lengthObj instanceof String) {
                    colLengthStr = (String) lengthObj;
                } else {
                    colLengthStr = "255"; // 默认长度，或者可以根据类型设置更合适的默认值
                    System.out.println("[WARN] 列 '" + colName + "' 长度未知，默认为 " + colLengthStr);
                }

                if(colName == null || colType == null) {
                    System.err.println("❌ (事务内) 表 " + tableName + " 的结构信息中存在不完整的列定义。");
                    throw new StorageException("表 " + tableName + " 结构信息不完整。");
                }
                schemaList.add(new String[]{colName, colType, colLengthStr});
            }
            System.out.println("[DEBUG] (事务内) 获取到表 [" + tableName + "] 的结构，包含 " + schemaList.size() + " 列");

            // 5. 解析插入值 (保留原有parseCSV逻辑)
            // JSqlParser .getValues() 返回一个 ValuesExpression 对象，其 .getExpressions() 返回 List<Expression>
            // 对于单行 INSERT VALUES (...), (...), ... 来说，需要更复杂的解析
            // 假设我们处理的是 INSERT INTO table VALUES (val1, val2, ...)
            // 或 INSERT INTO table (col1, col2) VALUES (val1, val2)
            // 目前的 parseCSV 适用于 VALUES (...) 形式
            if (insertStmt.getValues() == null) {
                 System.err.println("❌ INSERT 语句缺少 VALUES 子句。");
                 throw new StorageException("INSERT 语句缺少 VALUES 子句。");
            }
            String rawValues = insertStmt.getValues().toString(); // 这通常是 "(val1, val2, ...)"
            // 修正正则表达式中的转义字符
            String content = rawValues.replaceAll("(?i)^VALUES\\s*\\(|\\)$", "").trim();
            // 简单的移除 `VALUES (` 和 `)` 的方法，可能对复杂语句不够鲁棒
            // JSqlParser 的 insertStmt.getItemsList() 更好，但为了兼容现有 parseCSV，暂时这样
            // 暂时注释掉 getItemsList 的使用，以解决Linter错误，后续可根据JSqlParser确切版本调整
            /*
            if (insertStmt.getItemsList() != null && insertStmt.getItemsList().getExpressions() != null && !insertStmt.getItemsList().getExpressions().isEmpty()) {
                 // 这是更标准的解析方式，但需要调整以适配 parseCSV 或重写值提取
                 // List<Expression> valueExpressions = ((ExpressionList) insertStmt.getItemsList()).getExpressions();
                 // content = valueExpressions.stream().map(Expression::toString).collect(Collectors.joining(", "));
            }
            */

            List<String> values = parseCSV(content);
            System.out.println("[DEBUG] (事务内) 解析后的值: " + values);

            // 如果指定了列，需要确保值的数量与指定列的数量匹配
            // 如果未指定列，值的数量需要与表总列数匹配
            List<Column> targetColumns = insertStmt.getColumns();
            int expectedValuesCount = (targetColumns != null && !targetColumns.isEmpty()) ? targetColumns.size() : schemaList.size();

            if (values.size() != expectedValuesCount) {
                String reason = (targetColumns != null && !targetColumns.isEmpty()) ?
                                "与指定的列数 (" + expectedValuesCount + ")" :
                                "与表总列数 (" + expectedValuesCount + ")";
                System.err.println("❌ 提供的值数量 (" + values.size() + ") " + reason + " 不匹配");
                throw new StorageException("插入的值数量与列数量不匹配。");
            }

            // TODO: 如果 insertStmt.getColumns() 不为空, 需要根据指定的列顺序和名称来组织 values 和 schemaList
            // 当前是假设 values 的顺序与 schemaList (即表定义顺序) 一致。
            // 如果 INSERT INTO table (colC, colA) VALUES (valC, valA)，需要重新映射。
            // 这是一个重要的功能点，暂时标记为 TODO，当前实现要求 INSERT 语句列的顺序和表定义一致，或者不指定列名插入所有列。

            // 6. 调用事务化的 DataManager.insertData
            System.out.println("[DEBUG] (事务内) 准备执行 DataManager.insertData for " + tableName);
            // DataManager.insertData 应该接受数据库名、表名、值列表，以及（可选地）列顺序/模式。
            // 当前 DataManager.insertData(dbName, tableName, values, schemaList) 假设values与schemaList顺序对应。
            int result = DataManager.insertData(dbName, tableName, values, schemaList);

            if (result == 1) {
                System.out.println("✅ INSERT 语句已在事务中成功排队。");
                return 1;
            } else {
                // DataManager.insertData 应该在失败时抛出异常，而不是返回0（除非0有特定含义如"0行插入"）
                // 如果返回0表示已知错误（如唯一约束），它也应作为异常抛出由上层处理是否回滚。
                System.err.println("错误: DataManager.insertData 返回失败码 (" + result + ")，但未抛出异常。");
                throw new StorageException("DataManager.insertData 失败，返回码: " + result);
            }

        } catch (Exception e) {
            System.err.println("❌ INSERT 执行失败 (事务将回滚): " + (tableName != null ? "表 '"+tableName+"'" : "") + " - " + e.getMessage());
            // e.printStackTrace(); // 用于调试
            txLogger.rollbackTransaction();
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return 0;
        }
    }

    /**
     * 解析CSV格式的字符串，处理引号和逗号
     * 修复了处理括号、空格和引号的问题
     */
    private static List<String> parseCSV(String csvLine) {
        List<String> result = new ArrayList<>();
        boolean inQuotes = false;
        StringBuilder currentValue = new StringBuilder();
        
        // 预处理：去除最外层的括号（如果存在）
        if (csvLine.startsWith("(") && csvLine.endsWith(")")) {
            csvLine = csvLine.substring(1, csvLine.length() - 1);
        }

        // 检查并替换全角括号为半角括号
        csvLine = csvLine.replace('（', '(').replace('）', ')');
        
        System.out.println("[DEBUG] parseCSV处理输入: " + csvLine);
        
        for (int i = 0; i < csvLine.length(); i++) {
            char currentChar = csvLine.charAt(i);

            if (currentChar == '\'') {
                // 引号开始或结束
                inQuotes = !inQuotes;
                currentValue.append(currentChar);
            } else if (currentChar == ',' && !inQuotes) {
                // 逗号分隔符，但不在引号中
                result.add(currentValue.toString().trim());
                currentValue = new StringBuilder();
            } else {
                // 其他字符
                currentValue.append(currentChar);
            }
        }

        // 添加最后一个值
        if (currentValue.length() > 0) {
            result.add(currentValue.toString().trim());
        }
        
        System.out.println("[DEBUG] parseCSV解析结果: " + result);
        return result;
    }

    /**
     * 执行 SELECT 语句（事务性版本）
     * 新增特性：支持全字段查询（SELECT *）和条件查询
     *
     * @param selectStmt 解析后的SELECT语句对象
     * @return List<String[]> 查询结果集，每行为字符串数组
     */
    public static List<String[]> executeSelect(Select selectStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = null;
        String ownerName = null; // Added
        String currentSelectedTable = null; // For logging/error messages
        Session currentSession = Session.getCurrentSession();
        String sessionDbName = null;
        String sessionDbOwner = null;

        List<String[]> errorResult = new ArrayList<>();
        // Helper to create a single-row error result easily
        java.util.function.Function<String, List<String[]>> createError = (msg) -> {
            errorResult.add(new String[]{msg});
            return errorResult;
        };

        if (!txLogger.isTransactionActive()) {
            return createError.apply("错误: SELECT 操作需要在活动的事务中执行。请先使用 'USE database_name;'.");
        }
        try {
            dbName = txLogger.getTransactionDatabaseName();
            ownerName = txLogger.getTransactionOwnerName(); // Get owner from transaction
            if (dbName == null || ownerName == null) {
                 if(currentSession != null) currentSession.clearCurrentDatabaseAfterRollback();
                 return createError.apply("严重错误: 事务已激活但没有完整的数据库上下文(SELECT)。");
            }

            if (currentSession != null) {
                sessionDbName = currentSession.getCurrentDatabaseName();
                sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
            }
            if (sessionDbName == null || !sessionDbName.equals(dbName) || sessionDbOwner == null || !sessionDbOwner.equals(ownerName)) {
                 return createError.apply("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + ownerName + "." + dbName + "') 不符(SELECT)。");
            }

            if (!(selectStmt.getSelectBody() instanceof PlainSelect)) {
                 System.err.println("❌ SELECT 语句缺少有效的 FROM 子句。");
                 return new ArrayList<>();
            }
            PlainSelect plainSelect = (PlainSelect) selectStmt.getSelectBody();
            if (plainSelect.getFromItem() == null || !(plainSelect.getFromItem() instanceof Table)) {
                 System.err.println("❌ SELECT 语句缺少有效的 FROM 子句。");
                 return new ArrayList<>();
            }
            currentSelectedTable = ((Table) plainSelect.getFromItem()).getName();

            List<String> columnsToSelect = new ArrayList<>();
            if (plainSelect.getSelectItems().get(0).toString().equals("*")) {
                columnsToSelect = null; // DataManager.readSelectData 用 null 表示选择所有列
            } else {
                for (var item : plainSelect.getSelectItems()) {
                    columnsToSelect.add(item.toString());
                }
            }

            // 解析WHERE条件 (保留原有逻辑)
            String conditionColumn = null;
            String conditionValue = null;
            Expression where = plainSelect.getWhere();
            if (where != null) {
                if (where instanceof EqualsTo equals) {
                    String left = equals.getLeftExpression().toString();
                    // 简单处理列名，可能需要更健壮的解析来处理 table.column 格式
                    String[] colParts = left.split("\\."); // 使用双反斜杠转义点
                    conditionColumn = colParts[colParts.length - 1].toLowerCase();

                    Expression rightExpr = equals.getRightExpression();
                    if (rightExpr instanceof StringValue) {
                        conditionValue = ((StringValue) rightExpr).getValue(); // 直接获取字符串值，无需手动去引号
                    } else {
                        conditionValue = rightExpr.toString().replaceAll("^'|'$", ""); // 保留对其他表达式类型的处理，并去引号
                    }
                    if ("NULL".equalsIgnoreCase(conditionValue)) {
                         conditionValue = null; // SQL NULL 转换为 Java null
                    }
                } else {
                    System.err.println("❌ SELECT 目前仅支持简单的等于(column = 'value') WHERE 条件。");
                    return new ArrayList<>();
                }
            }

            // 移除旧的DB Name获取 (已在顶部通过事务获取)
            // String dbName = DatabaseManager.getCurrentDatabase();
            // Map<String, Object> tableInfo = TableManager.getTableInfo(dbName, tableName); // 表结构信息获取已移到DataManager内部或不再需要在此层面显式获取

            // 4. 调用事务化的 DataManager.readSelectData
            // DataManager.readSelectData 现在会优先使用事务DB
            System.out.println("[DEBUG] (事务内) 准备执行 DataManager.readSelectData for table '" + currentSelectedTable + "' in database '" + dbName + "'");
            List<String[]> result = DataManager.readSelectData(dbName, currentSelectedTable, columnsToSelect, conditionColumn, conditionValue);

            System.out.println("✅ SELECT 查询已在事务 '" + dbName + "' 中成功执行。影响行数: " + (result != null ? result.size() : 0));
            return result != null ? result : new ArrayList<>(); //确保不返回null

        } catch (Exception e) {
            // SELECT 查询失败通常不应回滚事务
            System.err.println("❌ SELECT 执行失败: " + (currentSelectedTable != null ? "表 '"+currentSelectedTable+"'" : "") + " in database '" + dbName + "' - " + e.getMessage());
            // e.printStackTrace(); // for debugging
            return new ArrayList<>(); // 返回空列表表示查询失败
        }
        // 不需要 finally 块来关闭DB，因为 readSelectData 会处理 (或使用事务DB不关闭)
    }

    /**
     * 执行 DELETE 语句。
     * @param deleteStmt Delete 语句对象
     * @return int 执行状态码：1 表示成功，0 表示失败
     */
    public static int executeDelete(Delete deleteStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = null;
        String ownerName = null; // Added
        String tableName = null;
        Session currentSession = Session.getCurrentSession();
        String sessionDbName = null;
        String sessionDbOwner = null;

        if (!txLogger.isTransactionActive()) {
            System.err.println("错误: DELETE 操作需要在活动的事务中执行。请先使用 'USE database_name;'.");
            return 0;
        }
        try {
            dbName = txLogger.getTransactionDatabaseName();
            ownerName = txLogger.getTransactionOwnerName(); // Get owner from transaction

            if (dbName == null || ownerName == null) {
                 System.err.println("严重错误: 事务已激活但没有完整的数据库上下文(DELETE)。");
                 if(currentSession != null) currentSession.clearCurrentDatabaseAfterRollback();
                 return 0;
            }

            if (currentSession != null) {
                sessionDbName = currentSession.getCurrentDatabaseName();
                sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
            }
            if (sessionDbName == null || !sessionDbName.equals(dbName) || sessionDbOwner == null || !sessionDbOwner.equals(ownerName)) {
                 System.err.println("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + ownerName + "." + dbName + "') 不符(DELETE)。");
                 return 0;
            }

            tableName = deleteStmt.getTable().getName();

            // 4. 解析WHERE条件 (保留原有逻辑, 细化错误处理)
            String conditionColumn = null;
            String conditionValue = null;
            Expression where = deleteStmt.getWhere();
            if (where != null) { // 允许没有where子句 (删除全部)
                 if (where instanceof EqualsTo equals) {
                     String left = equals.getLeftExpression().toString();
                     String[] colParts = left.split("\\."); // 使用双反斜杠转义点
                     conditionColumn = colParts[colParts.length - 1].toLowerCase();

                     Expression rightExpr = equals.getRightExpression();
                     if (rightExpr instanceof StringValue) {
                         conditionValue = ((StringValue) rightExpr).getValue();
                     } else {
                         conditionValue = rightExpr.toString().replaceAll("^'|'$", "");
                     }
                     if ("NULL".equalsIgnoreCase(conditionValue)) {
                          conditionValue = null;
                     }
                 } else {
                      System.err.println("❌ DELETE 目前仅支持简单的等于(column = 'value') WHERE 条件。复杂的WHERE条件: " + where);
                      throw new UnsupportedOperationException("不支持的WHERE条件类型: " + where.getClass().getName());
                 }
            }

            // 5. 调用事务化的 DataManager.deleteData
            System.out.println("[DEBUG] (事务内) 准备执行 DataManager.deleteData for table '" + tableName + "' in database '" + dbName + "'");
            // DataManager.deleteData 应该在失败时抛出异常
            int deletedCount = DataManager.deleteData(dbName, tableName, conditionColumn, conditionValue);

            // deleteData 内部如果失败会抛异常，如果成功返回删除的行数 (>=0)
            System.out.println("✅ DELETE 语句已在事务 '" + dbName + "' 中成功排队 (影响行数: " + deletedCount + ")。");
            return deletedCount; // 返回影响的行数 (>=0)

        } catch (UnsupportedOperationException e) { // 特别处理不支持的WHERE条件
            System.err.println("❌ DELETE 执行失败 (事务将回滚): " + (tableName != null ? "表 '"+tableName+"'" : "") + " - " + e.getMessage());
            txLogger.rollbackTransaction();
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return -1;
        } catch (Exception e) {
            System.err.println("❌ DELETE 执行失败 (事务将回滚): " + (tableName != null ? "表 '"+tableName+"'" : "") + " - " + e.getMessage());
            // e.printStackTrace(); // for debugging
            txLogger.rollbackTransaction();
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return -1; // 或者返回0？返回-1表示错误可能更清晰
        }
    }

    /**
     * 执行 UPDATE 语句。
     * @param updateStmt Update 语句对象
     * @return int 执行状态码：1 表示成功，0 表示失败
     */
    public static int executeUpdate(Update updateStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = null;
        String ownerName = null; // Added
        String tableName = null;
        Session currentSession = Session.getCurrentSession();
        String sessionDbName = null;
        String sessionDbOwner = null;

        if (!txLogger.isTransactionActive()) {
            System.err.println("错误: UPDATE 操作需要在活动的事务中执行。请先使用 'USE database_name;'.");
            return 0;
        }
        try {
            dbName = txLogger.getTransactionDatabaseName();
            ownerName = txLogger.getTransactionOwnerName(); // Get owner from transaction
            if (dbName == null || ownerName == null) {
                 System.err.println("严重错误: 事务已激活但没有完整的数据库上下文(UPDATE)。");
                 if(currentSession != null) currentSession.clearCurrentDatabaseAfterRollback();
                 return 0;
            }

            if (currentSession != null) {
                sessionDbName = currentSession.getCurrentDatabaseName();
                sessionDbOwner = currentSession.getCurrentDatabaseOwnerName();
            }
            if (sessionDbName == null || !sessionDbName.equals(dbName) || sessionDbOwner == null || !sessionDbOwner.equals(ownerName)) {
                 System.err.println("错误: 当前会话数据库 ('" + sessionDbOwner + "." + sessionDbName + "') 与活动事务数据库 ('" + ownerName + "." + dbName + "') 不符(UPDATE)。");
                 return 0;
            }

            tableName = updateStmt.getTable().getName();

            // >> 新增: 获取表结构信息 (schemaList) 以便传递给 DataManager
            System.out.println("[DEBUG] (事务内) UPDATE: 准备获取表结构: " + tableName + " 在数据库 " + dbName);
            Map<String, Object> tableInfoForUpdate = TableManager.getTableInfo(dbName, tableName);
            if (tableInfoForUpdate == null || tableInfoForUpdate.isEmpty() || !tableInfoForUpdate.containsKey("columns")) {
                System.err.println("❌ (事务内) UPDATE: 无法获取表 " + tableName + " 的结构信息。表可能不存在或无权限。");
                throw new StorageException("UPDATE: 无法获取表 " + tableName + " 的结构信息。");
            }
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> columnsInfoForUpdate = (List<Map<String, Object>>) tableInfoForUpdate.get("columns");
            if (columnsInfoForUpdate == null || columnsInfoForUpdate.isEmpty()) {
                 System.err.println("❌ (事务内) UPDATE: 表 " + tableName + " 的结构信息不包含列定义。");
                 throw new StorageException("UPDATE: 表 " + tableName + " 缺少列定义。");
            }
            List<String[]> schemaListForUpdate = new ArrayList<>();
            for (Map<String, Object> colInfo : columnsInfoForUpdate) {
                String colName = (String) colInfo.get("name");
                String colType = (String) colInfo.get("type");
                Object lengthObj = colInfo.get("length");
                String colLengthStr = (lengthObj instanceof Number) ? String.valueOf(((Number)lengthObj).intValue()) :
                                    (lengthObj instanceof String ? (String)lengthObj : "255");
                if(colName == null || colType == null) {
                    System.err.println("❌ (事务内) UPDATE: 表 " + tableName + " 的结构信息中存在不完整的列定义。");
                    throw new StorageException("UPDATE: 表 " + tableName + " 结构信息不完整。");
                }
                schemaListForUpdate.add(new String[]{colName, colType, colLengthStr});
            }
            System.out.println("[DEBUG] (事务内) UPDATE: 获取到表 [" + tableName + "] 的结构，包含 " + schemaListForUpdate.size() + " 列");
            // << 新增结束

            // 4. 解析 SET 子句 (保留原有逻辑, 细化错误处理)
            List<String> updateColumns = new ArrayList<>();
            List<String> updateValues = new ArrayList<>();
            List<Column> columns = updateStmt.getColumns();
            List<Expression> expressions = updateStmt.getExpressions();
            if (columns == null || expressions == null || columns.size() != expressions.size() || columns.isEmpty()){
                System.err.println("错误: UPDATE语句的SET子句无效。列数与值数量不匹配或为空。");
                throw new StorageException("UPDATE语句的SET子句无效。"); // 这会触发下面的catch并回滚
            }
            for (int i = 0; i < columns.size(); i++) {
                Column column = columns.get(i);
                String[] colParts = column.toString().split("\\."); // 使用双反斜杠转义点
                updateColumns.add(colParts[colParts.length - 1]); // 获取纯列名

                Expression expr = expressions.get(i);
                String value;
                if (expr instanceof StringValue) {
                    value = ((StringValue) expr).getValue(); // 直接获取无引号的字符串值
                } else if (expr.toString().equalsIgnoreCase("NULL")) {
                     value = null; // 将 SQL NULL 转为 Java null
                } else {
                    value = expr.toString(); // 其他类型直接用toString()
                }
                updateValues.add(value);
            }

            // 5. 解析 WHERE 条件 (保留原有逻辑, 细化错误处理)
            String conditionColumn = null;
            String conditionValue = null;
            Expression where = updateStmt.getWhere();
            if (where != null) { // 允许没有where (更新全部)
                if (where instanceof EqualsTo equals) {
                    String left = equals.getLeftExpression().toString();
                    String[] leftParts = left.split("\\.");  // 使用双反斜杠转义点
                    conditionColumn = leftParts[leftParts.length - 1].toLowerCase();

                    Expression rightExpr = equals.getRightExpression();
                    if (rightExpr instanceof StringValue) {
                        conditionValue = ((StringValue) rightExpr).getValue();
                    } else if (rightExpr.toString().equalsIgnoreCase("NULL")) {
                    } else {
                        conditionValue = rightExpr.toString().replaceAll("^'|'$", ""); // 对于非StringValue且非NULL，尝试去引号
                    }
                } else {
                     System.err.println("❌ UPDATE 目前仅支持简单的等于(column = 'value') WHERE 条件。复杂的WHERE条件: " + where);
                     throw new UnsupportedOperationException("不支持的WHERE条件类型: " + where.getClass().getName());
                }
            }

            // 6. 调用事务化的 DataManager.updateData
            System.out.println("[DEBUG] (事务内) 准备执行 DataManager.updateData for table '" + tableName + "' in database '" + dbName + "'");
            // DataManager.updateData 应在失败时抛出异常
            // 将 schemaListForUpdate 传递给 updateData
            int updatedCount = DataManager.updateData(dbName, tableName, conditionColumn, conditionValue, updateColumns, updateValues, schemaListForUpdate);

            System.out.println("✅ UPDATE 语句已在事务 '" + dbName + "' 中成功排队 (影响行数: " + updatedCount + ")。");
            return updatedCount; // 返回影响行数 (>=0)

        } catch (UnsupportedOperationException | StorageException e) { // 特别处理已知类型的可控异常
            System.err.println("❌ UPDATE 执行失败 (事务将回滚): " + (tableName != null ? "表 '"+tableName+"'" : "") + " - " + e.getMessage());
            txLogger.rollbackTransaction();
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return -1;
        } catch (Exception e) { // 捕获其他所有意外异常
            System.err.println("❌ UPDATE 执行中发生意外错误 (事务将回滚): " + (tableName != null ? "表 '"+tableName+"'" : "") + " - " + e.getMessage());
            // e.printStackTrace(); // for debugging
            txLogger.rollbackTransaction();
            Session currentSessionForRollback = Session.getCurrentSession();
            if (currentSessionForRollback != null) {
                currentSessionForRollback.clearCurrentDatabaseAfterRollback();
            }
            return -1; // 返回-1表示错误
        }
    }


    // 新增 USE 语句处理器
    /**
     * 执行USE语句，切换当前会话的默认数据库，并启动/切换事务。
     * 注意：此方法现在仅做验证，实际的数据库切换应在会话级别执行。
     *       但它将负责启动关联的事务。
     */
    public static int executeUseDatabase(UseStatement useStmt) {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        String dbName = useStmt.getName();
        String ownerName = null; // Will be set from current session

        try {
            // 如果存在活动的事务，并且不是针对同一个数据库，则先回滚
            if (txLogger.isTransactionActive()) {
                String activeTxDbOwner = txLogger.getTransactionOwnerName();
                String activeTxDbName = txLogger.getTransactionDatabaseName();
                if (activeTxDbName != null && (!activeTxDbName.equals(dbName) || activeTxDbOwner == null /* Need to get prospective owner to compare */ )) {
                    // We need to get the prospective owner for the new dbName to do a full comparison.
                    // For a simple USE dbName (parsed by JSqlParser), owner is the current user.
                    Session tempSession = Session.getCurrentSession();
                    String prospectiveOwner = (tempSession != null) ? tempSession.getUsername() : null;

                    if (prospectiveOwner == null) {
                        System.err.println("[WARN] SQLExecutor.executeUseDatabase: Cannot determine prospective owner for comparison. Rolling back if any active transaction.");
                        txLogger.rollbackTransaction(); // Rollback unconditionally if prospective owner is unknown and tx active
                        if (tempSession != null) tempSession.clearCurrentDatabaseAfterRollback();
                    } else if (!activeTxDbName.equals(dbName) || !activeTxDbOwner.equals(prospectiveOwner)) {
                        System.out.println("提示: 切换数据库，回滚当前数据库 '" + activeTxDbOwner + "." + activeTxDbName + "' 的活动事务。");
                        txLogger.rollbackTransaction();
                        if (tempSession != null) tempSession.clearCurrentDatabaseAfterRollback();
                    }
                }
            }

            Session currentSession = Session.getCurrentSession();
            if (currentSession != null) {
                ownerName = currentSession.getUsername(); // Get ownerName from current session
                if (ownerName == null) {
                    System.err.println("❌ SQLExecutor: 无法获取当前用户名作为数据库所有者 (executeUseDatabase)。");
                    return 0; // Or throw exception
                }
                System.out.println("[DEBUG] SQLExecutor: Calling currentSession.setCurrentDatabase('" + ownerName + "', '" + dbName + "')");
                // setCurrentDatabase now handles its own verbose logging.
                // It also checks existence and permissions internally.
                // It will also call DatabaseManager.setCurrentDatabase internally.
                boolean setDbSuccess = currentSession.setCurrentDatabase(ownerName, dbName);
                if (!setDbSuccess) {
                    // setCurrentDatabase would have printed an error message.
                    // We might not need to start a transaction if setting DB context failed.
                    System.err.println("❌ SQLExecutor: Session.setCurrentDatabase 失败 (executeUseDatabase)。事务可能不会启动。");
                    return 0; // Indicate failure
                }
            } else {
                System.err.println("[WARN] SQLExecutor: currentSession is null in executeUseDatabase.");
                return 0; // Cannot proceed without a session
            }

            // 只有在成功设置会话数据库后才启动事务
            System.out.println("[DEBUG] SQLExecutor: About to call txLogger.beginTransaction('" + ownerName + "', '" + dbName + "')");
            boolean txStarted = txLogger.beginTransaction(ownerName, dbName);
            System.out.println("[DEBUG] SQLExecutor: txLogger.beginTransaction returned: " + txStarted);

            if (!txStarted) {
                System.err.println("❌ SQLExecutor: 事务启动失败 (executeUseDatabase)。");
                // If transaction failed to start, we might want to clear the session's current DB context
                // as it might be in an inconsistent state.
                if (currentSession != null) {
                    currentSession.setCurrentDatabase(null, null); // Clear context
                }
                return 0; // Indicate failure
            }

            System.out.println("✅ (SQLExecutor) USE DATABASE " + ownerName + "." + dbName + " 执行成功，事务已启动。");
            return 1; // 成功

        } catch (Exception e) {
            System.err.println("❌ 执行 USE DATABASE 失败: " + e.getMessage());
            // Attempt to rollback if a transaction was somehow partially started or an old one was active
            if (txLogger.isTransactionActive()) {
                txLogger.rollbackTransaction();
                Session tempSession = Session.getCurrentSession();
                if (tempSession != null) tempSession.clearCurrentDatabaseAfterRollback();
            }
            return 0; // 失败
        }
    }

    /**
     * 执行 COMMIT 命令。
     * @return 1 如果提交成功, 0 如果没有活动事务或提交失败。
     */
    public static int executeCommit() {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        if (!txLogger.isTransactionActive()) {
            System.err.println("错误: 没有活动的事务可提交。请先使用 'USE database_name;'。");
            return 0; // 或者可以考虑抛出异常
        }

        if (txLogger.commitTransaction()) {
            return 1; // 提交成功
        } else {
            // commitTransaction 内部会打印错误信息
            return 0; // 提交失败
        }
    }

    /**
     * 执行 ROLLBACK 命令。
     * @return 1 如果回滚成功或无需回滚, 0 如果回滚操作本身失败。
     */
    public static int executeRollback() {
        TransactionLogger txLogger = TransactionLogger.getInstance();
        // 调用 rollbackTransaction, 它内部会处理没有活动事务的情况
        if (txLogger.rollbackTransaction()) {
            return 1; // 回滚成功或无事可做
        } else {
             // rollbackTransaction 内部会打印错误信息
            return 0; // 回滚失败
        }
    }

    /**
     * Parses the CreateTable statement to extract basic column definitions and
     * a list of pending constraints to be applied.
     *
     * @param createTable The JSqlParser CreateTable object.
     * @return ParsedCreateTableParts containing basic column definitions and pending constraints.
     */
    private static ParsedCreateTableParts parseSchema(CreateTable createTable) {
        List<String[]> basicColumnDefinitions = new ArrayList<>();
        List<PendingConstraintDetail> pendingConstraints = new ArrayList<>();
        String tableName = createTable.getTable().getName();

        // 1. Process column definitions (Column-level constraints)
        if (createTable.getColumnDefinitions() != null) {
            for (ColumnDefinition colDef : createTable.getColumnDefinitions()) {
                String colName = colDef.getColumnName();
                if (colDef.getColDataType() == null) {
                    throw new IllegalArgumentException("列 '" + colName + "' 必须指定数据类型");
                }
                String dataType = colDef.getColDataType().getDataType().toUpperCase();
                // 验证数据类型是否在允许范围内
                Set<String> allowedTypes = Set.of("INT", "INTEGER", "VARCHAR", "CHAR", "DATE",
                                                 "BOOLEAN", "DECIMAL", "NUMERIC", "TIMESTAMP");
                if (!allowedTypes.contains(dataType)) {
                    throw new IllegalArgumentException("列 '" + colName + "' 的数据类型 '" + dataType + "' 不被支持");
                }
                int length = 255;
                switch (dataType) {
                    case "VARCHAR": case "CHAR":
                        if (colDef.getColDataType().getArgumentsStringList() != null &&
                            !colDef.getColDataType().getArgumentsStringList().isEmpty()) {
                            try { length = Integer.parseInt(colDef.getColDataType().getArgumentsStringList().get(0)); }
                            catch (NumberFormatException e) { System.err.println("警告: 列 '" + colName + "' 长度解析失败 ("+ colDef.getColDataType().getArgumentsStringList().get(0) +")，使用默认值 " + length); }
                        }
                        break;
                    case "INT": case "INTEGER": length = 11; break;
                    case "DATE": length = 10; break;
                    case "BOOLEAN": length = 1; break;
                    case "DECIMAL": case "NUMERIC": length = 20; break;
                    case "TIMESTAMP": length = 19; break;
                    default:
                        throw new IllegalArgumentException("列 '" + colName + "' 的数据类型 '" + dataType + "' 不被支持");
                }
                basicColumnDefinitions.add(new String[]{colName, dataType, String.valueOf(length)});

                List<String> columnSpecs = colDef.getColumnSpecs();
                if (columnSpecs != null && !columnSpecs.isEmpty()) {
                    for (int i = 0; i < columnSpecs.size(); i++) {
                        String spec = columnSpecs.get(i).toUpperCase();
                        if ("NOT".equals(spec) && i + 1 < columnSpecs.size() && "NULL".equals(columnSpecs.get(i + 1).toUpperCase())) {
                            pendingConstraints.add(new PendingConstraintDetail("nn_" + tableName + "_" + colName, ConstraintType.NOT_NULL, java.util.Collections.singletonList(colName)));
                            i++;
                        } else if ("PRIMARY".equals(spec) && i + 1 < columnSpecs.size() && "KEY".equals(columnSpecs.get(i + 1).toUpperCase())) {
                            pendingConstraints.add(new PendingConstraintDetail("pk_" + tableName + "_" + colName, ConstraintType.PRIMARY_KEY, java.util.Collections.singletonList(colName)));
                            pendingConstraints.add(new PendingConstraintDetail("nn_" + tableName + "_" + colName + "_for_pkcol", ConstraintType.NOT_NULL, java.util.Collections.singletonList(colName)));
                            i++;
                        } else if ("UNIQUE".equals(spec)) {
                            pendingConstraints.add(new PendingConstraintDetail("uk_" + tableName + "_" + colName, ConstraintType.UNIQUE, java.util.Collections.singletonList(colName)));
                        } else if ("CHECK".equals(spec) && i + 1 < columnSpecs.size()) {
                             String checkExprStr = columnSpecs.get(i+1);
                             if (checkExprStr.startsWith("(") && checkExprStr.endsWith(")")) {
                                 checkExprStr = checkExprStr.substring(1, checkExprStr.length() - 1);
                             }
                             PendingConstraintDetail pcdCheck = new PendingConstraintDetail("chk_" + tableName + "_" + colName + "_" + (System.currentTimeMillis()%1000), ConstraintType.CHECK, java.util.Collections.singletonList(colName));
                             pcdCheck.setCheckDetails(checkExprStr);
                             pendingConstraints.add(pcdCheck);
                             i++;
                        } else if ("REFERENCES".equals(spec) && i + 1 < columnSpecs.size()) {
                            String refTableAndColSpec = columnSpecs.get(i+1);
                            Pattern fkPattern = Pattern.compile("(\\w+)(?:\\s*\\((.+)\\))?");
                            Matcher fkMatcher = fkPattern.matcher(refTableAndColSpec);
                            if (fkMatcher.find()) {
                                String refTable = fkMatcher.group(1);
                                List<String> refCols = new ArrayList<>();
                                if (fkMatcher.group(2) != null) {
                                     String[] parsedRefCols = fkMatcher.group(2).split(",");
                                     for(String rc : parsedRefCols) refCols.add(rc.trim());
                                }
                                if (!refTable.isEmpty()) {
                                     PendingConstraintDetail pcdFk = new PendingConstraintDetail("fk_" + tableName + "_" + colName, ConstraintType.FOREIGN_KEY, java.util.Collections.singletonList(colName));
                                     pcdFk.setForeignKeyDetails(refTable, refCols.isEmpty() ? java.util.Collections.singletonList(colName) : refCols);
                                     pendingConstraints.add(pcdFk);
                                }
                            }
                            i++;
                        }
                    }
                }
            }
        }

        if (createTable.getIndexes() != null) {
            for (Index index : createTable.getIndexes()) {
                String constraintName = index.getName();
                List<String> constraintCols = new ArrayList<>();
                if (index.getColumns() != null) {
                    for(Index.ColumnParams colParam : index.getColumns()){
                        constraintCols.add(colParam.getColumnName());
                    }
                }
                if (index.getType() == null || constraintCols.isEmpty()) continue;

                String typeUpper = index.getType().toUpperCase();
                if (typeUpper.equals("PRIMARY KEY")) {
                    if (constraintName == null) constraintName = "pk_" + tableName;
                    pendingConstraints.add(new PendingConstraintDetail(constraintName, ConstraintType.PRIMARY_KEY, constraintCols));
                    for(String pkCol : constraintCols) {
                         pendingConstraints.add(new PendingConstraintDetail("nn_" + tableName + "_" + pkCol + "_for_pk", ConstraintType.NOT_NULL, java.util.Collections.singletonList(pkCol)));
                    }
                } else if (typeUpper.equals("UNIQUE") || typeUpper.equals("UNIQUE KEY")) {
                    if (constraintName == null) constraintName = "uk_" + tableName + "_" + String.join("_", constraintCols);
                    pendingConstraints.add(new PendingConstraintDetail(constraintName, ConstraintType.UNIQUE, constraintCols));
                } else if (index instanceof ForeignKeyIndex) {
                    ForeignKeyIndex fkIndex = (ForeignKeyIndex) index;
                    if (constraintName == null) constraintName = "fk_" + tableName + "_" + String.join("_", constraintCols);
                    
                    String refTable = fkIndex.getTable().getName();
                    List<String> refCols = new ArrayList<>();
                    if (fkIndex.getReferencedColumnNames() != null) {
                        refCols.addAll(fkIndex.getReferencedColumnNames());
                    }
                    
                    // 如果引用列为空，假设引用的是父表中的相同列名
                    if (refCols.isEmpty()) {
                        refCols.addAll(constraintCols);
                    }
                    
                    if (refTable != null && !refTable.isEmpty() && !constraintCols.isEmpty() && !refCols.isEmpty()) {
                        PendingConstraintDetail pcdFk = new PendingConstraintDetail(constraintName, ConstraintType.FOREIGN_KEY, constraintCols);
                        pcdFk.setForeignKeyDetails(refTable, refCols);
                        pendingConstraints.add(pcdFk);
                        System.out.println("[DEBUG] 添加表级FOREIGN KEY约束: " + constraintName + " 引用表: " + refTable);
                    } else {
                        System.out.println("警告: 表级 FOREIGN KEY 约束定义不完整，无法解析。");
                    }
                } else if (typeUpper.equals("CHECK")) {
                     System.out.println("警告: 通过 INDEX 定义的表级 CHECK 约束 ('"+constraintName+"') 的表达式解析目前不可靠，建议通过 ALTER TABLE ADD CONSTRAINT 添加。");
                }
            }
        }

        List<PendingConstraintDetail> finalPendingConstraints = new ArrayList<>();
        Map<String, String> uniqueConstraintSignatures = new HashMap<>();
        for (PendingConstraintDetail pcd : pendingConstraints) {
            String signaturePart = pcd.type + ":" + String.join(",", pcd.columns.stream().sorted().collect(Collectors.toList()));
            if (pcd.type == ConstraintType.NOT_NULL || pcd.type == ConstraintType.PRIMARY_KEY || pcd.type == ConstraintType.UNIQUE || pcd.type == ConstraintType.FOREIGN_KEY || pcd.type == ConstraintType.CHECK ){
                String fullSignature = signaturePart;
                if (pcd.name != null) {
                    fullSignature = pcd.name;
                } else {
                     if (pcd.type == ConstraintType.NOT_NULL && pcd.name != null && pcd.name.contains("_for_pk")) {
                     } else if (uniqueConstraintSignatures.containsKey(fullSignature)) {
                         System.out.println("[DEBUG] parseSchema: Skipping duplicate-signature pending constraint: " + fullSignature);
                         continue;
                     }
                }
                uniqueConstraintSignatures.put(fullSignature, pcd.name != null ? pcd.name : "unnamed_auto_generated");
                finalPendingConstraints.add(pcd);
            } else {
                finalPendingConstraints.add(pcd);
            }
        }
        return new ParsedCreateTableParts(basicColumnDefinitions, finalPendingConstraints);
    }

    // Removed parseSchema_OLD method

    public static int executeGrantPrivilege(String ownerName, String dbName, String targetUser) {
        Session currentSession = Session.getCurrentSession();
        if (currentSession == null) {
            System.err.println("❌ GRANT 操作失败: 用户未登录。");
            return 0;
        }

        if (!security.auth.UserManager.userExists(targetUser)) {
            System.err.println("❌ GRANT 操作失败: 目标用户 '" + targetUser + "' 不存在。");
            return 0;
        }

        // 数据库存在性检查将在 systemDBEngine.grantPrivilege 内部处理（通过dbKey查找）
        // if (!storage.manager.DatabaseManager.databaseExists(dbName)) { // This check needs to consider owner
        // System.err.println("❌ GRANT 操作失败: 数据库 '" + ownerName + "." + dbName + "' 不存在。");
        // return 0;
        // }

        try {
            core.engine.systemDBEngine.grantPrivilege(ownerName, dbName, targetUser);
            return 1; // 成功
        } catch (core.exceptions.DBEngineException e) {
            System.err.println("❌ GRANT 操作失败: " + e.getMessage());
            return 0;
        }
    }

    public static int executeRevokePrivilege(String ownerName, String dbName, String targetUser) {
        Session currentSession = Session.getCurrentSession();
        if (currentSession == null) {
            System.err.println("❌ REVOKE 操作失败: 用户未登录。");
            return 0;
        }

        if (!security.auth.UserManager.userExists(targetUser)) {
            System.err.println("❌ REVOKE 操作失败: 目标用户 '" + targetUser + "' 不存在。");
            return 0;
        }

        // 数据库存在性检查将在 systemDBEngine.revokePrivilege 内部处理
        // if (!storage.manager.DatabaseManager.databaseExists(dbName)) { // This check needs to consider owner
        // System.err.println("❌ REVOKE 操作失败: 数据库 '" + ownerName + "." + dbName + "' 不存在。");
        // return 0;
        // }

        try {
            core.engine.systemDBEngine.revokePrivilege(ownerName, dbName, targetUser);
            return 1; // 成功
        } catch (core.exceptions.DBEngineException e) {
            System.err.println("❌ REVOKE 操作失败: " + e.getMessage());
            return 0;
        }
    }

    public static int executeDeleteDatabase(String ownerName, String dbName) {
        Session currentSession = Session.getCurrentSession();
        String currentUser = null;
        if (currentSession != null) {
            currentUser = currentSession.getUsername();
        }

        if (currentUser == null) {
            System.err.println("❌ DELETE DATABASE 操作失败: 用户未登录。");
            return 0;
        }

        if ("system_db".equalsIgnoreCase(dbName)) {
            System.err.println("❌ 不能删除系统数据库 'system_db'。");
            return 0;
        }

        try {
            // DatabaseManager.deleteDatabase 将处理权限和物理删除
            // 它内部会调用 systemDBEngine.deleteDatabaseMetadata
            return DatabaseManager.deleteDatabase(ownerName, dbName); 
        } catch (StorageException e) {
            System.err.println("❌ DELETE DATABASE 操作失败: " + e.getMessage());
            return 0;
        }
    }

}

